package com.unbox.generate.controller;

import com.unbox.common.response.UnboxResponse;
import com.unbox.common.util.ZipFilesUtil;
import com.unbox.generate.entity.GenerateConfig;
import com.unbox.generate.entity.DBInfo;
import com.unbox.generate.entity.GenerateInfo;
import com.unbox.generate.entity.UnboxGenerateConfig;
import com.unbox.generate.service.IGeneratorService;
import com.unbox.generate.service.IUnboxGenerateConfigService;
import com.unbox.generate.util.Freemarker;
import com.unbox.generate.util.StringUtil;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.SpringQueryMap;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.io.*;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.zip.ZipOutputStream;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author jobob
 * @since 2021-02-25
 */
@RestController
public class UnboxGenerateConfigController {
    private static final Logger logger = LoggerFactory.getLogger(UnboxGenerateConfigController.class);

    @Autowired
    IUnboxGenerateConfigService generateConfigService;

    @Autowired
    IGeneratorService generatorService;

    @Autowired
    Freemarker freemarker;

    /**
     * 获取配置信息
     * @return
     */
    @GetMapping(value = "/getTableList", consumes = MediaType.APPLICATION_JSON_VALUE)
    public UnboxResponse getTableList(@SpringQueryMap DBInfo tableInfo) {
        try {
            List list = generatorService.getTableList(tableInfo);
            return new UnboxResponse<>(list);
        } catch (SQLException e) {
            logger.error(e.getMessage());
        } catch (ClassNotFoundException e) {
            logger.error(e.getMessage());
        }
        return new UnboxResponse
                .Builder()
                .businessFail()
                .build();
    }

    /**
     * 生成代码
     * @param generateConfig
     * @return
     */
    @PostMapping(value = "/generate")
    public UnboxResponse generate(@RequestBody GenerateConfig generateConfig) {
        try {

            // 1 生成后端 2生成前端
            switch (generateConfig.getType()) {
                case 1:
                    generateConfig.setGenerateType("xml");
                    freemarker.mapperXml(generateConfig);
                    generateConfig.setGenerateType("mapper");
                    freemarker.mapper(generateConfig);
                    generateConfig.setGenerateType("entity");
                    freemarker.entity(generateConfig);
                    generateConfig.setGenerateType("service");
                    freemarker.service(generateConfig);
                    generateConfig.setGenerateType("serviceImpl");
                    freemarker.serviceImpl(generateConfig);
                    generateConfig.setGenerateType("hystrix");
                    freemarker.hystrix(generateConfig);
                    generateConfig.setGenerateType("fegin");
                    freemarker.fegin(generateConfig);
                    generateConfig.setGenerateType("controller");
                    freemarker.controller(generateConfig);
                    break;
                case 2:
                    // 筛选数据验证参数
                    Optional<GenerateInfo> flug = generateConfig.getGenerateInfos().stream()
                        .filter(generateInfo -> {
                          if (generateInfo.getWebEditFlug() && StringUtils.isEmpty(generateInfo.getWebEditControl())) {
                              return true;
                          }
                          if (generateInfo.getWebSelectFlug() && StringUtils.isEmpty(generateInfo.getWebSelectControl())) {
                              return true;
                          }
                          if (generateInfo.getWebTableListFlug() && StringUtils.isEmpty(generateInfo.getWebTableControl())) {
                              return true;
                          }
                          return false;
                        }).findAny();
                    if (flug.isPresent()) {
                        return new UnboxResponse.Builder<Boolean>().businessFail("请选择需要生成控件").build();
                    }
                    generateConfig.setGenerateType("apiJs");
                    freemarker.apiJs(generateConfig);
                    generateConfig.setGenerateType("vueList");
                    freemarker.vueList(generateConfig);
                    generateConfig.setGenerateType("vueEdit");
                    freemarker.vueEdit(generateConfig);
                    break;
                default:
            }
            return new UnboxResponse<>();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        }
        return new UnboxResponse
                .Builder()
                .businessFail()
                .build();
    }

    /**
     * 获得表信息
     * @param tableInfo
     * @return
     */
    @GetMapping(value = "/getTableInfo", consumes = MediaType.APPLICATION_JSON_VALUE)
    public UnboxResponse getTableInfo(@SpringQueryMap DBInfo tableInfo) {
        try {
            List list = generatorService.getTableInfo(tableInfo);
            return new UnboxResponse<>(list);
        } catch (SQLException e) {
            logger.error(e.getMessage());
        } catch (ClassNotFoundException e) {
            logger.error(e.getMessage());
        }
        return new UnboxResponse
                .Builder()
                .businessFail()
                .build();
    }

    /**
     * 下载导出来的文件
     * @return
     */
    @RequestMapping(path = "/downloadZip", method = RequestMethod.GET)
    public ResponseEntity<byte[]> downloadZip() {
        String url = System.getProperty("user.dir")+"/generator";
        File sourceDir = new File(url);
        File zipFile = new File(url+".zip");
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(new FileOutputStream(zipFile));
            String baseDir = "generator/";
            ZipFilesUtil.compress(sourceDir, baseDir, zos);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally{
            if(zos!=null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        ResponseEntity<byte[]> responseEntity = returnFile(zipFile);
        if (zipFile.exists()) {
            zipFile.delete();
        }
        delFile(new File(url));
        return responseEntity;
    }

    /**
     * 删除文件夹
     * @param file
     * @return
     */
    boolean delFile(File file) {
        if (!file.exists()) {
            return false;
        }

        if (file.isFile()) {
            return file.delete();
        } else {
            File[] files = file.listFiles();
            for (File f : files) {
                delFile(f);
            }
            return file.delete();
        }
    }

    /**
     * 下载文件
     * @param fileDatas
     * @return
     */
    public ResponseEntity<byte[]> returnFile(File fileDatas) {
        try {
            InputStream inputStream = new FileInputStream(fileDatas);
            byte[] fileData = InputStreamToByte(inputStream);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            headers.setContentDispositionFormData("attachment", simpleDateFormat.format(new Date())+".zip");
            ResponseEntity<byte[]> files = new ResponseEntity<byte[]>(fileData, headers, HttpStatus.CREATED);
            inputStream.close();
            return files;
        } catch (Exception e) {
        }
        return  null;
    }

    public byte[] InputStreamToByte(InputStream iStrm) throws IOException {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        int ch;
        while ((ch = iStrm.read()) != -1)
        {
            byteStream.write(ch);
        }
        byte[] imgData =byteStream.toByteArray();
        byteStream.close();
        return imgData;
    }

    /**
     * 获取配置信息
     * @return
     */
    @GetMapping("/getConfig")
    public UnboxResponse getConfig() {
        return new UnboxResponse<>( generateConfigService.getById(1));
    }

    /**
     * 保存配置信息
     * @param unboxGenerateConfig
     * @return
     */
    @PostMapping("/saveConfig")
    public UnboxResponse saveConfig(@RequestBody UnboxGenerateConfig unboxGenerateConfig) {
        generateConfigService.saveOrUpdate(unboxGenerateConfig);
        return new UnboxResponse<>(true);
    }
}
